// =====================================================================
// <copyright file="OpResult.cs" author="David R. Guindo">
// 	Copyright (C) 2013. All rights reserved.
// </copyright>
// =====================================================================
// This code is released under the terms of the Apache 2.0 license, 
// http://apache.org/licenses/LICENSE-2.0.html
// =====================================================================

namespace AppBlock.Core
{
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using ICollection = System.Collections.ICollection;

    public class OpResult<T> : OpResult<T, Exception>
    {
        public OpResult(T result) : base(result)
        {
        }

        public OpResult(ResultType status, T result) : base(status, result)
        {
        }

        public OpResult(Exception ex) : base(ex)
        {
        }

        public OpResult(Exception ex, T result) : base(ex, result)
        {
        }
    }

    public class OpResult<T, TException> where TException : Exception
    {
        private ResultType? status;

        /// <summary>
        ///     Gets or sets the exception.
        /// </summary>
        /// <value>
        ///     The exception.
        /// </value>
        public TException Exception { get; set; }

        public OpResult(T result)
        {
            this.Value = result;
        }

        public OpResult(ResultType status, T result)
        {
            this.Value = result;
            this.Status = status;
        }

        public OpResult(TException ex, T result = default(T))
        {
            this.Status = ResultType.Error;
            this.Value = result;
            this.Exception = ex;
        }

        public ResultType Status
        {
            get
            {
                if (status != null) return (ResultType) status;
                if (this.Exception != null) return ResultType.Error;
                return this.Count == 0 ? ResultType.Empty : ResultType.HasResults;
            }
            private set { status = value; }
        }

        public T Value { get; private set; }

        public int Count
        {
            get
            {
                if (this.Value.Equals(null)) return 0;
                if (this.Value is ICollection<object>)
                {
                    var collection = this.Value as ICollection;
                    if (collection != null) return collection.Count;
                }
#pragma warning disable 0618
                if (this.Value is IEnumerable<object>) return (this.Value as IEnumerable).Count();
#pragma warning restore 0618
                return 1;
            }
        }
    }
}